package com.atguigu.mock;

import cn.hutool.core.lang.WeightRandom;
import cn.hutool.core.util.RandomUtil;
import com.atguigu.common.util.CsvHelper;
import com.atguigu.common.util.DateUtil;
import com.atguigu.mock.entity.*;
import com.atguigu.mock.repository.*;
import com.github.javafaker.Faker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Component
public class MockMain {

    // repository
    private final CustomerRepository customerRepository;
    private final OrderInfoRepository orderInfoRepository;
    private final OrderDetailRepository orderDetailRepository;
    private final OrderStatusLogRepository orderStatusLogRepository;
    private final PaymentRepository paymentRepository;
    private final ProductCategoryRepository productCategoryRepository;
    private final ProductGroupRepository productGroupRepository;
    private final ProductSkuRepository productSkuRepository;
    private final ProductSpuAttrRepository productSpuAttrRepository;
    private final ProductSpuAttrValueRepository productSpuAttrValueRepository;
    private final ProductSpuRepository productSpuRepository;
    private final PromotionRepository promotionRepository;
    private final RegionRepository regionRepository;
    private final ShopRepository shopRepository;

    @Autowired
    private EntityManager entityManager;

    // 工具类
    private final CsvHelper csvHelper;
    private final DateUtil dateUtil;
    private final Faker faker;

    // 全局状态变量
    private LocalDateTime currentTime;
    @Value("${mock.enthusiasm}")
    private Double enthusiasm;
    @Value("${mock.days}")
    private int days;


    // 全局数据，模拟时需要调用
    private List<Customer> customerList;
    private List<OrderInfo> orderInfoList;
    private List<OrderDetail> orderDetailList;
    private List<OrderStatusLog> orderStatusLogList;
    private List<Payment> paymentList;
    private List<ProductCategory> productCategoryList;
    private List<ProductGroup> productGroupList;
    private List<ProductSku> productSkuList;
    private List<ProductSpu> productSpuList;
    private List<ProductSpuAttr> productSpuAttrList;
    private List<ProductSpuAttrValue> productSpuAttrValueList;
    private List<Promotion> promotionList;
    private List<Region> regionList;
    private List<Shop> shopList;

    private final WeightRandom<Integer> downstream = new WeightRandom<>();
    private final WeightRandom<String> downCommentStream = new WeightRandom<>();

    public MockMain(CustomerRepository customerRepository, OrderInfoRepository orderInfoRepository, OrderDetailRepository orderDetailRepository, OrderStatusLogRepository orderStatusLogRepository, PaymentRepository paymentRepository, ProductCategoryRepository productCategoryRepository, ProductGroupRepository productGroupRepository, ProductSkuRepository productSkuRepository, ProductSpuAttrRepository productSpuAttrRepository, ProductSpuAttrValueRepository productSpuAttrValueRepository, ProductSpuRepository productSpuRepository, PromotionRepository promotionRepository, RegionRepository regionRepository, ShopRepository shopRepository, CsvHelper csvHelper, DateUtil dateUtil, Faker faker) {
        this.customerRepository = customerRepository;
        this.orderInfoRepository = orderInfoRepository;
        this.orderDetailRepository = orderDetailRepository;
        this.orderStatusLogRepository = orderStatusLogRepository;
        this.paymentRepository = paymentRepository;
        this.productCategoryRepository = productCategoryRepository;
        this.productGroupRepository = productGroupRepository;
        this.productSkuRepository = productSkuRepository;
        this.productSpuAttrRepository = productSpuAttrRepository;
        this.productSpuAttrValueRepository = productSpuAttrValueRepository;
        this.productSpuRepository = productSpuRepository;
        this.promotionRepository = promotionRepository;
        this.regionRepository = regionRepository;
        this.shopRepository = shopRepository;
        this.csvHelper = csvHelper;
        this.dateUtil = dateUtil;
        this.faker = faker;
    }

    // 初始化维度数据
    public void initData() {
        Optional<OrderInfo> lastElement = orderInfoRepository.findFirstByOrderByUpdateTimeDesc();
        boolean isInit = !lastElement.isPresent();
        currentTime = isInit ? dateUtil.firstDay(8) : dateUtil.newDay(lastElement.get().getUpdateTime(), 8);
        if (isInit) {
            // 初始化维度数据
            mockRegion();
            mockShop();
            mockPromotion();
            mockCustomer();
            mockCategory();
            mockSpu();
            mockSku();
            mockSpuAttr();
            mockSpuAttrValue();
            mockSkuGroup();
        } else {
            // 读取所有维度数据
            customerList = customerRepository.findAll();
            productCategoryList = productCategoryRepository.findAll();
            productGroupList = productGroupRepository.findAll();
            productSkuList = productSkuRepository.findAll();
            productSpuList = productSpuRepository.findAll();
            productSpuAttrList = productSpuAttrRepository.findAll();
            productSpuAttrValueList = productSpuAttrValueRepository.findAll();
            promotionList = promotionRepository.findAll();
            regionList = regionRepository.findAll();
            shopList = shopRepository.findAll();
        }


        // 初始化所有业务表ID
        orderInfoRepository.findFirstByOrderByIdDesc();
        customerRepository.findFirstByOrderByIdDesc();
        orderDetailRepository.findFirstByOrderByIdDesc();
        orderInfoRepository.findFirstByOrderByIdDesc();
        orderStatusLogRepository.findFirstByOrderByIdDesc();
        paymentRepository.findFirstByOrderByIdDesc();
        productCategoryRepository.findFirstByOrderByIdDesc();
        productGroupRepository.findFirstByOrderByIdDesc();
        productSkuRepository.findFirstByOrderByIdDesc();
        productSpuAttrRepository.findFirstByOrderByIdDesc();
        productSpuAttrValueRepository.findFirstByOrderByIdDesc();
        productSpuRepository.findFirstByOrderByIdDesc();
        promotionRepository.findFirstByOrderByIdDesc();
        regionRepository.findFirstByOrderByIdDesc();
        shopRepository.findFirstByOrderByIdDesc();

        // 按照需要读取业务数据
        orderInfoList = orderInfoRepository.findByStatusIn(Arrays.asList(1, 2, 3, 5));
        orderDetailList = orderDetailRepository.findByOrderInfoIn(orderInfoList);
        orderStatusLogList = orderStatusLogRepository.findByOrderInfoIn(orderInfoList);
        paymentList = paymentRepository.findByStatusIn(Collections.singleton(1));

        // 筛选存在未完成支付记录的订单
        Set<Long> unFinishedPaymentOrderIds = new HashSet<>();
        paymentList.forEach(
                payment -> unFinishedPaymentOrderIds.add(payment.getOrderInfo().getId()));

        // 筛选下单待支付的订单
        List<OrderInfo> needToPay = orderInfoRepository.findByStatusIn(Collections.singletonList(1));

        needToPay.stream()
                .filter(orderInfo -> !unFinishedPaymentOrderIds.contains(orderInfo.getId()))
                .forEach(orderInfo -> {
                    LocalDateTime paymentCreateTime = dateUtil.later(currentTime, RandomUtil.randomInt(5 * 1000, 15 * 1000));
                    paymentList.add(orderInfo.generatePayment(paymentCreateTime, paymentCreateTime));
                });
    }

    private void mockSkuGroup() {
        productGroupList = new ArrayList<>();
        List<ProductSku> chickenList = productSkuList.stream().filter(sku -> sku.getProductCategory().getName().equals("鸡排")).collect(Collectors.toList());
        List<ProductSku> hamburgerList = productSkuList.stream().filter(sku -> sku.getProductCategory().getName().equals("汉堡")).collect(Collectors.toList());
        List<ProductSku> friesList = productSkuList.stream().filter(sku -> sku.getProductCategory().getName().equals("小吃")).collect(Collectors.toList());
        List<ProductSku> colaList = productSkuList.stream().filter(sku -> sku.getProductCategory().getName().equals("饮料")).collect(Collectors.toList());
        int flag = 1;
        int total = 100;
        for (ProductSku chicken : chickenList) {
            for (ProductSku hamburger : hamburgerList) {
                for (ProductSku fries : friesList) {
                    for (ProductSku cola : colaList) {
                        productGroupList.add(new ProductGroup(currentTime, Arrays.asList(chicken, hamburger, fries, cola), "套餐" + (flag++)));
                        if (flag > total) {
                            break;
                        }
                    }
                    if (flag > total) {
                        break;
                    }
                }
                if (flag > total) {
                    break;
                }
            }
            if (flag > total) {
                break;
            }
        }
        productGroupRepository.saveAll(productGroupList);
    }

    private void mockSpuAttrValue() {
        productSpuAttrValueList = new ArrayList<>();
        for (ProductSpuAttr productSpuAttr : productSpuAttrList) {
            switch (productSpuAttr.getAttrName()) {
                case "火候":
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "三分熟"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "五分熟"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "全熟"));
                    break;
                case "酱料":
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "不要酱"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "少酱"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "正常酱"));
                    break;
                case "口味":
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "不要辣"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "少辣"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "正常辣"));
                    break;
                case "冰块":
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "不要冰"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "少冰"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "正常冰"));
                    break;
                case "甜度":
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "五分糖"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "七分糖"));
                    productSpuAttrValueList.add(new ProductSpuAttrValue(currentTime, productSpuAttr, "全糖"));
                    break;
            }
        }
        productSpuAttrValueRepository.saveAll(productSpuAttrValueList);
    }

    private void mockSpuAttr() {
        productSpuAttrList = new ArrayList<>();
        for (ProductSpu productSpu : productSpuList) {
            switch (productSpu.getProductCategory().getName()) {
                case "鸡排":
                    productSpuAttrList.add(new ProductSpuAttr(currentTime, productSpu, "火候"));
                case "汉堡":
                case "小吃":
                    productSpuAttrList.add(new ProductSpuAttr(currentTime, productSpu, "酱料"));
                    productSpuAttrList.add(new ProductSpuAttr(currentTime, productSpu, "口味"));
                    break;
                case "饮料":
                    productSpuAttrList.add(new ProductSpuAttr(currentTime, productSpu, "甜度"));
                    productSpuAttrList.add(new ProductSpuAttr(currentTime, productSpu, "冰块"));
                    break;
            }
        }
        productSpuAttrRepository.saveAll(productSpuAttrList);
    }

    private void mockSku() {
        productSkuList = new ArrayList<>();
        for (ProductSpu productSpu : productSpuList) {
            productSkuList.add(new ProductSku(currentTime, productSpu, "小", new BigDecimal(RandomUtil.randomInt(15, 25))));
            productSkuList.add(new ProductSku(currentTime, productSpu, "中", new BigDecimal(RandomUtil.randomInt(25, 35))));
            productSkuList.add(new ProductSku(currentTime, productSpu, "大", new BigDecimal(RandomUtil.randomInt(35, 45))));
        }
        productSkuRepository.saveAll(productSkuList);
    }

    private void mockSpu() {
        productSpuList = new ArrayList<>();
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(0), "那么大鸡排", "很大的鸡排"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(0), "那么香鸡排", "很香的鸡排"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(0), "那么辣鸡排", "很辣的鸡排"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(0), "那么甜鸡排", "很甜的鸡排"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(0), "那么咸鸡排", "很咸的鸡排"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(1), "那么大汉堡", "很大的汉堡"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(1), "那么香汉堡", "很香的汉堡"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(1), "那么辣汉堡", "很辣的汉堡"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(1), "那么甜汉堡", "很甜的汉堡"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(1), "那么咸汉堡", "很咸的汉堡"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(2), "那么大薯条", "很大的薯条"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(2), "那么香薯条", "很香的薯条"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(2), "那么辣薯条", "很辣的薯条"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(2), "那么甜薯条", "很甜的薯条"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(2), "那么咸薯条", "很咸的薯条"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(3), "那么大可乐", "很大的可乐"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(3), "那么香可乐", "很香的可乐"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(3), "那么辣可乐", "很辣的可乐"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(3), "那么甜可乐", "很甜的可乐"));
        productSpuList.add(new ProductSpu(currentTime, productCategoryList.get(3), "那么咸可乐", "很咸的可乐"));

        productSpuRepository.saveAll(productSpuList);
    }

    private void mockCategory() {
        productCategoryList = new ArrayList<>();
        productCategoryList.add(new ProductCategory(currentTime, "鸡排", "所有鸡排"));
        productCategoryList.add(new ProductCategory(currentTime, "汉堡", "所有汉堡"));
        productCategoryList.add(new ProductCategory(currentTime, "小吃", "所有小吃和配餐"));
        productCategoryList.add(new ProductCategory(currentTime, "饮料", "所有饮料"));
        productCategoryRepository.saveAll(productCategoryList);
    }

    private void mockCustomer() {
        customerList = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            customerList.add(new Customer(currentTime, faker.name().username(), faker.phoneNumber().phoneNumber()));
        }
        customerRepository.saveAll(customerList);
    }

    private void mockPromotion() {
        promotionList = new ArrayList<>();
        promotionList.add(new Promotion(currentTime, "满减券1", new BigDecimal(30), new BigDecimal(5), new BigDecimal("0.7")));
        promotionList.add(new Promotion(currentTime, "满减券1", new BigDecimal(50), new BigDecimal(10), new BigDecimal("0.7")));
        promotionList.add(new Promotion(currentTime, "满减券1", new BigDecimal(100), new BigDecimal(25), new BigDecimal("0.7")));
        promotionList.add(new Promotion(currentTime, "满减券1", new BigDecimal(200), new BigDecimal(60), new BigDecimal("0.7")));
        promotionList.sort((p1, p2) -> p2.getThresholdAmount().compareTo(p1.getThresholdAmount()));
        promotionRepository.saveAll(promotionList);

    }

    private void mockShop() {
        shopList = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            shopList.add(new Shop(currentTime, faker.funnyName().name(),
                    RandomUtil.randomInt(1, 3),
                    RandomUtil.randomEle(regionList.stream().filter(region -> region.getLevel() == 2).collect(Collectors.toList())),
                    faker.phoneNumber().phoneNumber()));
        }
        shopRepository.saveAll(shopList);
    }

    private void mockRegion() {
        regionList = csvHelper.csvToEntities(currentTime, "dim/Region.csv", Region.class);
        regionRepository.saveAll(regionList);
    }

    // 模拟业务数据
    public void mockData() {
        generateCustomer();
        generateOrder();
        payForBill();
        cooking();
        rating();
        refund();
        refundPayment();
    }

    private void generateCustomer() {
        if (RandomUtil.randomDouble() < enthusiasm * 0.01) {
            customerList.add(new Customer(currentTime, faker.name().username(), faker.phoneNumber().phoneNumber()));
        }
    }

    public void handleOrderInfo(long minActionMillis, int currentStatus, WeightRandom<Integer> downstream, Consumer<? super OrderInfo> customAction) {
        this.orderInfoList.stream()
                .filter(oi -> !oi.isModified())
                .filter(oi -> oi.getStatus() == currentStatus)
                .filter(oi -> dateUtil.longEnough(oi.getUpdateTime(), currentTime, minActionMillis, 0))
                .filter(oi -> RandomUtil.randomDouble() < enthusiasm * 0.1)
                .peek(oi -> {
                    Integer nextStatus = downstream.next();
                    if (nextStatus != currentStatus) {
                        if (nextStatus != 5 || oi.getRating() < 3) {
                            oi.setUpdateTime(currentTime);
                            OrderStatusLog resultStatus = new OrderStatusLog(currentTime, oi, nextStatus);
                            orderStatusLogList.add(resultStatus);
                            oi.setStatus(nextStatus);
                        }
                    }
                })
                .forEach(customAction);
    }

    public void handleOrderInfo(long minActionMillis, int currentStatus, WeightRandom<Integer> downstream) {
        handleOrderInfo(minActionMillis, currentStatus, downstream, oi -> {
        });
    }

    public void handlePayment(long minActionMillis, long maxActionMillis, int currentStatus, WeightRandom<Integer> downstream, Consumer<? super Payment> customAction) {
        this.paymentList.stream()
                .filter(payment -> {
                    OrderInfo orderInfo = payment.getOrderInfo();
                    LocalDateTime orderTime = orderInfo.getCreateTime();
                    LocalDateTime paymentTime = payment.getCreateTime();
                    return !dateUtil.longEnough(orderTime, paymentTime, maxActionMillis);
                })
                .filter(payment -> payment.getStatus() == currentStatus)
                .filter(payment -> dateUtil.longEnough(payment.getCreateTime(), currentTime, minActionMillis))
                .peek(payment -> {
                    payment.setUpdateTime(dateUtil.later(payment.getCreateTime(), RandomUtil.randomInt(45 * 1000, 60 * 1000)));
                    payment.setStatus(downstream.next());
                })
                .collect(Collectors.toList())
                .forEach(customAction);
    }

    public void handlePayment(long minActionMillis, int currentStatus, WeightRandom<Integer> downstream, Consumer<? super Payment> customAction) {
        this.paymentList.stream()
                .filter(payment -> !payment.isModified())
                .filter(payment -> payment.getStatus() == currentStatus)
                .filter(payment -> dateUtil.longEnough(payment.getUpdateTime(), currentTime, minActionMillis, 0))
                .filter(payment -> RandomUtil.randomDouble() < enthusiasm * 0.1)
                .peek(payment -> {
                    payment.setUpdateTime(currentTime);
                    payment.setStatus(downstream.next());
                })
                .forEach(customAction);
    }

    private void generateOrder() {
        if (RandomUtil.randomDouble() < enthusiasm * 0.1) {
            OrderInfo orderInfo = new OrderInfo(currentTime, RandomUtil.randomEle(customerList), RandomUtil.randomEle(shopList));
            if (RandomUtil.randomDouble() < 0.5) {
                OrderDetail detail = new OrderDetail(currentTime, orderInfo, null, RandomUtil.randomEle(productGroupList), 1);
                orderDetailList.add(detail);
                orderInfo.acceptDetail(detail);
            } else {
                int count = RandomUtil.randomInt(1, 5);
                for (int i = 0; i < count; i++) {
                    OrderDetail detail = new OrderDetail(currentTime, orderInfo, RandomUtil.randomEle(productSkuList), null, RandomUtil.randomInt(1, 3));
                    orderDetailList.add(detail);
                    orderInfo.acceptDetail(detail);
                }
            }

            for (Promotion promotion : promotionList) {
                if (orderInfo.acceptPromotion(promotion)) {
                    break;
                }
            }
            if (RandomUtil.randomDouble() < 0.95) {
                LocalDateTime paymentCreateTime = dateUtil.later(currentTime, RandomUtil.randomInt(5 * 1000, 15 * 1000));
                Payment payment = orderInfo.generatePayment(paymentCreateTime, paymentCreateTime);
                paymentList.add(payment);
            }
            orderInfoList.add(orderInfo);
        }

    }

    private void payForBill() {
        handlePayment(45 * 1000, 86400 * 1000, 1, downstream.clear().add(2, 0.95).add(3, 0.05), payment -> {
            if (payment.getStatus() == 2) {
                OrderInfo orderInfo = payment.getOrderInfo();
                orderInfo.setUpdateTime(payment.getUpdateTime());
                OrderStatusLog orderStatusLog = new OrderStatusLog(payment.getUpdateTime(), orderInfo, 2);
                orderInfo.setStatus(2);
                orderStatusLogList.add(orderStatusLog);
            } else if (payment.getStatus() == 3) {
                LocalDateTime retryTime = dateUtil.later(payment.getUpdateTime(), RandomUtil.randomInt(10 * 1000, 15 * 1000));
                paymentList.add(payment.getOrderInfo().generatePayment(retryTime, retryTime));
            }
        });
    }

    private void cooking() {
        handleOrderInfo(120000, 2, downstream.clear().add(3, 1));
    }

    private void rating() {
        downCommentStream.clear().add("好吃！", 0.95).add("马马虎虎", 0.04).add("化身喷射战士！", 0.01);
        handleOrderInfo(60 * 60 * 1000, 3, downstream.clear().add(4, 1),
                oi -> {
                    String comment = downCommentStream.next();
                    oi.setComment(comment);

                    if (comment.equals("好吃！")) {
                        oi.setRating(RandomUtil.randomInt(4, 6));
                    } else if (comment.equals("马马虎虎")) {
                        oi.setRating(RandomUtil.randomInt(2, 4));
                    } else {
                        oi.setRating(RandomUtil.randomInt(1, 2));
                    }
                });
    }

    private void refund() {
        handleOrderInfo(60 * 60 * 1000, 4, downstream.clear().add(4, 0.50).add(5, 0.50),
                oi -> {
                    if (oi.isModified()) {
                        paymentList.stream()
                                .filter(payment -> Objects.equals(payment.getOrderInfo().getId(), oi.getId()))
                                .filter(payment -> payment.getStatus() == 2)
                                .forEach(payment -> {
                                    payment.setUpdateTime(currentTime);
                                    payment.setStatus(4);
                                });
                    }
                });
    }

    private void refundPayment() {
        handlePayment(60000, 4, downstream.clear().add(5, 1), pay -> {
            OrderInfo orderInfo = pay.getOrderInfo();
            orderInfo.setUpdateTime(currentTime);
            OrderStatusLog orderStatusLog = new OrderStatusLog(currentTime, orderInfo, 6);
            orderInfo.setStatus(6);
            orderStatusLogList.add(orderStatusLog);
        });
    }


    // 持久化模拟的数据
    private void persistAll() {
        customerRepository.saveAll(customerList);
        orderInfoRepository.saveAll(orderInfoList);
        orderStatusLogRepository.saveAll(orderStatusLogList);
        orderDetailRepository.saveAll(orderDetailList);
        paymentRepository.saveAll(paymentList);
    }

    @Transactional
    public void run() {
        for (int j = 0; j < days; j++) {
            System.out.println("初始化数据中...");
            initData();
            for (int i = 0; i < 960; i++) {
                System.out.print("\r" + "正在模拟" + currentTime);
                mockData();
                persistAll();
                currentTime = dateUtil.later(currentTime, 60 * 1000);
                entityManager.flush();
            }

            System.out.println();
        }

    }

}
